#include "cipher.h"
#include <openssl/des.h>
#include <QDebug>

#define DES_BLOCK_SIZE 8

C3Des::C3Des(QObject *parent) : CCipher(parent)
{
    ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER_CTX_init(ctx);
}

bool C3Des::encryption(const QByteArray& in, QByteArray& out, const QByteArray& key, const QByteArray& ivec, const EVP_CIPHER *cipher, bool enc)
{
    if (enc)  //加密
    {
        int ret = EVP_EncryptInit_ex(ctx, cipher, NULL, (const unsigned char*)key.data(), (const unsigned char*)ivec.data());
        if(ret != 1)
        {
            return false;
        }
        int len1 = 0;  //update输出的长度
        out.resize(in.size() + DES_BLOCK_SIZE);

        ret = EVP_EncryptUpdate(ctx, (unsigned char*)out.data(), &len1, (const unsigned char*)in.data(), in.size());
        if(ret != 1)
        {
            return false;
        }

        int len2 = 0;  //final输出的长度
        ret = EVP_EncryptFinal_ex(ctx, (unsigned char *)out.data() + len1, &len2);
        if(ret != 1)
        {
            return false;
        }
        out.resize(len1 + len2); //总长度
        return true;
    }
    else //解密
    {
        int ret = EVP_DecryptInit_ex(ctx, cipher, NULL, (const unsigned char*)key.data(), (const unsigned char*)ivec.data());
        if(ret != 1)
        {
            return false;
        }

        int len1 = 0;  //update输出的长度
        out.resize(in.size());
        ret = EVP_DecryptUpdate(ctx, (unsigned char*)out.data(), &len1, (const unsigned char*)in.data(), in.size());
        if(ret != 1)
        {
            return false;
        }

        int len2 = 0;  //final输出的长度
        ret = EVP_DecryptFinal_ex(ctx, (unsigned char *)out.data() + len1, &len2);
        if(ret != 1)
        {
            return false;
        }
        out.resize(len1 + len2); //总长度
        return true;
    }
}

//C3Des:
bool C3Des::encrypt(const QByteArray &in, QByteArray &out, const QByteArray &key, bool enc, int mode)
{
    if(mode == 0)//ecb模式
    {
        int Paddingsize = 24 - key.size();
        QByteArray newkey(key);
        newkey.append(Paddingsize, 0);

         // 根据key大小创建EVP_CIPHER
        const EVP_CIPHER * cipher = nullptr;
        cipher=EVP_des_ede3();
        // 执行加解密
        return encryption(in, out, newkey, QByteArray(), cipher, enc);
    }
    else if(mode == 1) //cbc模式
    {
        int Paddingsize = 24 - key.size();
        QByteArray newkey(key);
        newkey.append(Paddingsize, 0);
        Q_ASSERT(ivec.size() == 8); // 初始向量为8字节

        const EVP_CIPHER * cipher = nullptr;
        cipher=EVP_des_ede3_cbc();
        // 执行加解密
        return encryption(in, out, newkey, ivec , cipher, enc);

    }
    else if(mode == 2) // cfb模式
    {
        int Paddingsize = 24 - key.size();
        QByteArray newkey(key);
        newkey.append(Paddingsize, 0);
        Q_ASSERT(ivec.size() == 8); // 初始向量为8字节

        const EVP_CIPHER * cipher = nullptr;
        cipher=EVP_des_ede3_cfb();
        // 执行加解密
        return encryption(in, out, newkey, ivec , cipher, enc);
    }
    else if(mode == 3) // ofb模式
    {
        int Paddingsize = 24 - key.size();
        QByteArray newkey(key);
        newkey.append(Paddingsize, 0);
        Q_ASSERT(ivec.size() == 8); // 初始向量为8字节

        const EVP_CIPHER * cipher = nullptr;
        cipher=EVP_des_ede3_ofb() ;
        // 执行加解密
        return encryption(in, out, newkey, ivec , cipher, enc);
    }
}

bool C3Des::encrypt(const QByteArray &in, QByteArray &out, const QByteArray &key, bool enc, int mode, const QByteArray &ivec)
{

}

bool C3Des::encrypt(const QByteArray &in,QByteArray &out,int mode)
{
}
